--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Commit 1ae7cea2b60b29efd6fb110e5ddce3069236c06c
Parents : 581e807
Author : Mark Qvist <mark@unsigned.io>
Date : 2025-11-24T13:38:20+01:00
Added in-call profile switching for voice calls. Improved voice call UI feedback on establishment failure.
Changes
4 files changed, 38 insertions(+), 9 deletions(-)
Diff
diff --git a/sbapp/sideband/core.py b/sbapp/sideband/core.py
index 4a33e77e..f77a251f 100644
--- a/sbapp/sideband/core.py
+++ b/sbapp/sideband/core.py
@@ -2026,6 +2026,7 @@ class SidebandCore():
elif "telephone_announce" in call: connection.send(self.telephone.announce() if self.telephone else False)
elif "telephone_get_call_log" in call: connection.send(self.telephone.get_call_log() if self.telephone else [])
elif "telephone_clear_call_log" in call: connection.send(self.telephone.clear_call_log() if self.telephone else False)
+ elif "telephone_switch_profile" in call: connection.send(self.telephone.switch_profile(call["telephone_switch_profile"]) if self.telephone else False)
else:
connection.send(None)
diff --git a/sbapp/sideband/voice.py b/sbapp/sideband/voice.py
index 92dcabdd..9e39ced0 100644
--- a/sbapp/sideband/voice.py
+++ b/sbapp/sideband/voice.py
@@ -39,6 +39,7 @@ class ReticulumTelephone():
self.direction = None
self.last_input = None
self.first_run = False
+ self.user_hung_up = False
self.ringtone_path = None
self.speaker_device = speaker
self.microphone_device = microphone
@@ -110,7 +111,10 @@ class ReticulumTelephone():
self.telephone.teardown()
self.telephone = None
- def hangup(self): self.telephone.hangup()
+ def hangup(self):
+ self.user_hung_up = True
+ self.telephone.hangup()
+
def answer(self): self.telephone.answer(self.caller)
def set_busy(self, busy): self.telephone.set_busy(busy)
def set_low_latency_output(self, enabled): self.telephone.set_low_latency_output(enabled)
@@ -192,6 +196,9 @@ class ReticulumTelephone():
self.direction = "to"
self.telephone.call(self.caller, profile=profile)
+ def switch_profile(self, profile):
+ self.telephone.switch_profile(profile)
+
def ringing(self, remote_identity):
if self.hw_state == self.HW_STATE_SLEEP: self.hw_state = self.HW_STATE_IDLE
self.state = self.STATE_RINGING
@@ -205,6 +212,8 @@ class ReticulumTelephone():
call_was_connecting = self.call_is_connecting
was_ringing = self.is_ringing
was_in_call = self.is_in_call
+ user_hung_up = self.user_hung_up
+ self.user_hung_up = False
if self.is_in_call or self.is_ringing or self.call_is_connecting:
if self.is_in_call: RNS.log(f"Call with {RNS.prettyhexrep(self.caller.hash)} ended\n", RNS.LOG_DEBUG)
@@ -215,7 +224,7 @@ class ReticulumTelephone():
if call_was_connecting:
self.log_call("outgoing-failure", remote_identity)
- self.owner.setstate("voice.connection_failure", True)
+ if not user_hung_up: self.owner.setstate("voice.connection_failure", True)
elif was_in_call:
self.log_call("ongoing-ended", remote_identity)
self.owner.ended_call(remote_identity)
@@ -284,4 +293,5 @@ class ReticulumTelephoneProxy():
def set_low_latency_output(self, enabled): return self.owner.service_rpc_request({"telephone_set_low_latency_output": enabled})
def announce(self): return self.owner.service_rpc_request({"telephone_announce": True})
def get_call_log(self): return self.owner.service_rpc_request({"telephone_get_call_log": True})
- def clear_call_log(self): return self.owner.service_rpc_request({"telephone_clear_call_log": True})
\ No newline at end of file
+ def clear_call_log(self): return self.owner.service_rpc_request({"telephone_clear_call_log": True})
+ def switch_profile(self, profile): return self.owner.service_rpc_request({"telephone_switch_profile": profile})
\ No newline at end of file
diff --git a/sbapp/ui/voice.py b/sbapp/ui/voice.py
index 4060a6c3..b54fb109 100644
--- a/sbapp/ui/voice.py
+++ b/sbapp/ui/voice.py
@@ -96,7 +96,8 @@ class Voice():
ih.disabled = True
rb.disabled = True
db.disabled = False
- pb.disabled = True
+ if telephone.call_is_connecting: pb.disabled = True
+ if telephone.is_in_call: pb.disabled = False
db.text = "Hang up"
db.icon = "phone-hangup"
if telephone.active_profile: self.call_profile = telephone.active_profile
@@ -183,10 +184,24 @@ class Voice():
toast("Path request timed out")
def call_profile_action(self, sender=None):
- pb = self.screen.ids.call_profile_button
- self.call_profile = Profiles.next_profile(self.call_profile)
- pb.text = Profiles.profile_abbrevation(self.call_profile)
- toast(f"Call Profile: {Profiles.profile_name(self.call_profile)}")
+ if self.app.sideband.telephone.is_in_call: self.switch_profile_action()
+ else:
+ pb = self.screen.ids.call_profile_button
+ self.call_profile = Profiles.next_profile(self.call_profile)
+ pb.text = Profiles.profile_abbrevation(self.call_profile)
+ toast(f"Call Profile: {Profiles.profile_name(self.call_profile)}")
+
+ def switch_profile_action(self, sender=None):
+ if self.initial_call_profile == None: self.initial_call_profile = self.call_profile
+ if self.initial_call_profile < Profiles.QUALITY_MEDIUM: alt_profile = Profiles.QUALITY_MEDIUM
+ else: alt_profile = Profiles.BANDWIDTH_LOW
+ switch_profiles = [alt_profile, self.initial_call_profile]
+ if self.call_profile == switch_profiles[0]:
+ RNS.log(f"Switching to {Profiles.profile_name(switch_profiles[1])}", RNS.LOG_DEBUG)
+ self.app.sideband.telephone.switch_profile(switch_profiles[1])
+ else:
+ RNS.log(f"Switching to {Profiles.profile_name(switch_profiles[0])}", RNS.LOG_DEBUG)
+ self.app.sideband.telephone.switch_profile(switch_profiles[0])
def clear_log_action(self, sender=None):
self.app.sideband.telephone.clear_call_log()
@@ -210,6 +225,7 @@ class Voice():
if self.app.sideband.voice_running:
if self.app.sideband.telephone.is_ringing:
self.app.sideband.telephone.hangup()
+ self.initial_call_profile = None
def dial_action(self, sender=None):
if self.app.sideband.voice_running:
@@ -233,6 +249,8 @@ class Voice():
self.app.sideband.telephone.answer()
self.update_call_status()
+ self.initial_call_profile = None
+
### Settings screen
######################################
diff --git a/setup.py b/setup.py
index 86332d04..28c14fc7 100644
--- a/setup.py
+++ b/setup.py
@@ -126,7 +126,7 @@ setuptools.setup(
"lxst>=0.4.2",
"mistune>=3.0.2",
"beautifulsoup4",
- "pycodec2>=4.1.0;sys.platform!='Windows' and sys.platform!='win32' and sys.platform!='darwin'",
+ "pycodec2>=4.1.0",
"pyaudio;sys.platform=='linux'",
"pyobjus;sys.platform=='darwin'",
"pyogg;sys.platform=='Windows' and sys.platform!='win32'",
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────